const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`;
const qnameCapture = `((?:${ncname}\\:)?${ncname})`;
const startTagopen = new RegExp(`^<${qnameCapture}`); //匹配标签名 <div
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`);// </div>
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/; //匹配属性 key value
const startTagclose = /^\s*(\/?)>/;// 《br/》

export function parseHTML(html) {// html 开始<
    // console.log("html", html)
    const ELEMENT_TYPE = 1
    const TEXT_TYPE = 3
    const stack = []//存放元素
    let currentParent;// 指向栈最后一个
    let root

    function createASTElement(tag, attrs) {
        return {
            tag,
            type: ELEMENT_TYPE,
            children: [],
            attrs,
            parent: null
        }

    }

    // 转化成抽象语法树 栈
    function start(tag, attrs) {
        // console.log(tag, attrs, '开始标签');
        let node = createASTElement(tag, attrs)//创造节点
        if (!root) {//空树
            root = node// 根节点
        }
        if (currentParent) {
            node.parent = currentParent//
            currentParent.children.push(node)//父亲记住自己
        }
        stack.push(node)
        currentParent = node//为最后一个


    }
    function chars(text) {//文本直接放到当前指向的节点
        // console.log('text',text)
        text = text.replace(/\s/g, '')
        text && currentParent.children.push({
            type: TEXT_TYPE,
            text,
            parent: currentParent
        })
        // console.log(text, '文本');

    }
    function end(tag) {
        // console.log(tag, '结束标签');
        let node = stack.pop()//弹出最后一个， 校验标签
        currentParent = stack[stack.length - 1]

    }

    function advance(n) {
        html = html.substring(n)
    }
    function parseStartTag() {
        const start = html.match(startTagopen)// 索引0 标签字符串 索引1标签名
        if (start) {
            const match = {
                tagName: start[1],
                attrs: []//标签名
            }
            advance(start[0].length)
            // 不是开始标签的结束就一直匹配下去
            let attr, end
            while (!(end = html.match(startTagclose)) && (attr = html.match(attribute))) {
                advance(attr[0].length)
                match.attrs.push({
                    name: attr[1],
                    value: attr[3] || attr[4] || attr[5] || true
                })
            }
            // 匹配到开始标签的尾部“>”去掉
            if (end) {
                advance(end[0].length)
            }
            // console.log(match)
            return match
        }



        // console.log(html)

        return false

    }
    
    while (html) {
        let textEnd = html.indexOf('<')
        if (textEnd == 0) {// 索引为0则是开始或结束标签，
            const startTagMatch = parseStartTag()
            if (startTagMatch) {//解析到开始标签
                start(startTagMatch.tagName, startTagMatch.attrs)
                continue
            }

            let endTagMatch = html.match(endTag)
            if (endTagMatch) {
                advance(endTagMatch[0].length)
                end(endTagMatch[1])
                continue
            }
        }
        if (textEnd >= 0) { //>0为文本的结束位置
            let text = html.substring(0, textEnd)//提取文本内容
            if (text) {//解析到文本
                chars(text)
                advance(text.length)
            }
        }
    }
    // console.log(root)
    return root
}
